﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SMS.Entities.BaseClasses;
using SMS.Common.Silverlight;
using SMS.Model;
using System.Linq;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Collections;
using SMS.Entities.Master;
namespace SMS.ViewModel.Login
{
    public class LoginPageViewModel : BaseNotify, INotifyDataErrorInfo
    {
        /// <summary>
        /// Grid Control.
        /// </summary>
        Grid objGridLayout;
        /// <summary>
        /// TextBox Control.
        /// </summary>
        TextBox objTxtAccount;

        /// <summary>
        /// PasswordBox Control.
        /// </summary>
        PasswordBox objTxtPassword;
        /// <summary>
        /// Grid Control
        /// </summary>
        Grid grid;
        /// <summary>
        /// AuthenticationModel Object
        /// </summary>
        AuthenticationModel authenticate;
        /// <summary>
        /// UserLoginInformation Object
        /// </summary>
        readonly UserLoginInformationlist objUserLoginInfo;
        /// <summary>
        /// UserInfo Property
        /// </summary>
        public UserInfo UserInformation { get; set; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="_grid"></param>
        #region Page Constructor
        public LoginPageViewModel(Grid _grid)
        {
            objUserLoginInfo = new UserLoginInformationlist();
            UserInformation = new UserInfo();
            IntializeCommands();
            grid = _grid;
            IntializeModel();
            this.errors = new Dictionary<string, List<string>>();
            var storedInfo = GetUserInfoFromStorage();
            if (storedInfo != null)
            {
                UserName = storedInfo.UserName;
                Password = storedInfo.Password;
                //SelectedMaster = storedInfo.Branch;
                IsRememberMe = true;
            }

        }

        private void IntializeCommands()
        {
            this.GridControlLoadCommand = new DelegateCommand(GridControlCommandLoaded, null);
            this.LoginCommand = new DelegateCommand(Login_Clicked, null);
            this.ResetCommand = new DelegateCommand(Reset_Click, null);
            this.LoginFormGotFocusCommand = new DelegateCommand(LoginFormGotFocus_Command, null);
            this.InputLoginFormTextChangeCommand = new DelegateCommand(InputLoginFormTextChange_Command, null);
        }

        private void IntializeModel()
        {
            authenticate = new AuthenticationModel();
            authenticate.AuthenticationCompleted += new Action<Entities.Admin.ApplicationUser>(authenticate_AuthenticationCompleted);
        }
        #endregion

        #region Methods

        /// <summary>
        /// Assign GridControl object to 'objGridLayout'.
        /// </summary>
        /// <param name="param"></param>
        private void GridControlCommandLoaded(object param)
        {
            /* Find and set Grid Control */
            var gd = param as Grid;
            objGridLayout = gd;

            if (objGridLayout != null)
            {
                #region "Find and set TextBox Controls"
                var textBoxList = ControlFinder.GetChildren<TextBox>(objGridLayout);
                foreach (var tbx in textBoxList.Where(tbx => tbx.Name == "txt_UserName"))
                {
                    objTxtAccount = tbx;
                }
                if (objTxtAccount != null) { objTxtAccount.Focus(); }
                #endregion

                #region "Find and set PasswordBox Controls"
                var passwordBoxList = ControlFinder.GetChildren<PasswordBox>(objGridLayout);
                foreach (var pbx in passwordBoxList.Where(pbx => pbx.Name == "txt_Password"))
                {
                    objTxtPassword = pbx;
                }
                #endregion

            }
        }


        private void LoginFormGotFocus_Command(object param)
        {
            if (param != null)
            {
                switch (param.GetType().Name)
                {
                    case "TextBox":
                        objTxtAccount.SelectAll();
                        break;
                    case "PasswordBox":
                        objTxtPassword.SelectAll();
                        break;
                }
            }
        }

        private void Reset_Click(object param)
        {
            UserName = string.Empty;
            Password = string.Empty;
            objTxtAccount.Focus();
        }

        private void InputLoginFormTextChange_Command(object param)
        {
            if (param != null)
            {
                switch (param.GetType().Name)
                {
                    case "TextBox":
                        UserName = objTxtAccount.Text.Trim();
                        break;
                    case "PasswordBox":
                        Password = objTxtPassword.Password.Trim();
                        break;
                }
            }
        }

        public void Login_Clicked(object param)
        {
            if (param != null && UserInformation != null)
            {
                UserName = (param as UserInfo).UserName;
                Password = (param as UserInfo).Password;
            }

            #region "For Validations"
            var allErrors = new Dictionary<string, List<string>>();

            foreach (var err in errors)
            {
                allErrors.Add(err.Key, err.Value);
            }
            foreach (var prvError in allErrors)
            {
                RemoveErrorFromProperty(prvError.Key, null, true);
            }

            errors.Clear();

            this.ValidationResults = new ObservableCollection<ValidationResult>();

            bool isValid = Validator.TryValidateObject(this, new ValidationContext(this, null, null), this.ValidationResults, true);
            if (!isValid)
            {

                foreach (ValidationResult vr in ValidationResults)
                {
                    string[] msgs = { vr.ErrorMessage };
                    AddErrorToProperty(((string[])(vr.MemberNames))[0], msgs, true);
                }
                return;
            }
            #endregion

            BusyContent = "Authenticating...";
            IsBusy = true;

            if (!string.IsNullOrWhiteSpace(UserName) && !string.IsNullOrWhiteSpace(Password))
            {
                authenticate.AuthenticateUser(UserName, Password, true);

                if (IsRememberMe)
                {
                    ///Write in isolated stroage here...
                    RememberUserNameAndPassword(false);
                }
                else
                {
                    ///Delete storge here..
                    RememberUserNameAndPassword(true);
                }
            }
            else
            {
                IsBusy = false;
                ErrorMessage = "Please select Branch";
            }
        }

        void authenticate_AuthenticationCompleted(Entities.Admin.ApplicationUser obj)
        {

            if (obj == null)
            {
                ErrorMessage = "Wrong Username/Password";
                //UserName = Password = string.Empty;
            }
            else
            {
                App.CurrentSalesMan = obj.SalesMan;
                var _userinfo = new UserInfo()
                {
                    Login_ID = obj.Login_ID,
                    Password = obj.Password,
                    DisplayName = obj.DisplayName,
                    UserName = obj.UserName,
                    FirstName = obj.FirstName,
                    LastLogin = obj.LastLogin,
                    LastActivity = obj.LastActivity,
                    LastName = obj.LastName,
                    PicturePath = obj.PicturePath,
                    SalesMan = obj.SalesMan,
                    Role = obj.Role,
                    Email = obj.Email,
                    SessionDuration = 30
                };
                objUserLoginInfo.UserLoginInfo = _userinfo;
                using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForSite())
                {
                    if (store.FileExists("Login.dat"))
                        store.DeleteFile("Login.dat");

                    if (!store.FileExists("Login.dat"))
                    {
                        IsolatedStorageFileStream stream = store.CreateFile("Login.dat");
                        var serializer = new DataContractSerializer(typeof(UserInfo));
                        serializer.WriteObject(stream, objUserLoginInfo.UserLoginInfo);
                        stream.Close();
                    }
                    MainPage mainpage = new MainPage(obj);
                    grid.Children.Clear();
                    grid.Children.Add(mainpage);
                }
            }
            IsBusy = false;
        }

        private void RememberUserNameAndPassword(bool IsDelete)
        {
            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForSite())
            {
                if (store.FileExists("logindetail.dat"))
                    store.DeleteFile("logindetail.dat");
                if (!IsDelete)
                {
                    if (!store.FileExists("logindetail.dat"))
                    {
                        IsolatedStorageFileStream stream = store.CreateFile("logindetail.dat");
                        var serializer = new DataContractSerializer(typeof(UserInfo));
                        serializer.WriteObject(stream, new UserInfo { UserName = this.UserName, Password = this.Password, Branch=SelectedMaster });
                        stream.Close();
                    }
                }
                //MainPage mainpage = new MainPage(obj);
                //grid.Children.Clear();
                //grid.Children.Add(mainpage);
            }
        }

        private UserInfo GetUserInfoFromStorage()
        {
            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForSite())
            {
                if (store.FileExists("logindetail.dat"))
                {

                    IsolatedStorageFileStream stream = store.OpenFile("logindetail.dat", System.IO.FileMode.Open);
                    var serializer = new DataContractSerializer(typeof(UserInfo));
                    var userInfo = serializer.ReadObject(stream);
                    stream.Close();
                    return userInfo as UserInfo;
                }
                return null;
                //MainPage mainpage = new MainPage(obj);
                //grid.Children.Clear();
                //grid.Children.Add(mainpage);
            }
        }

        #endregion

        #region Properties

        private SMS.Entities.SalesManDetail _salesManObject;

        public SMS.Entities.SalesManDetail salesManObject
        {
            get { return _salesManObject; }
            set { _salesManObject = value; OnPropertyChanged("salesManObject"); }
        }


        private string _UserName;
        [Required(ErrorMessage = "User Name is required.")]
        public string UserName
        {
            get { return _UserName; }
            set { _UserName = value; OnPropertyChanged(UserName); }
        }

        private string _Password;
        [Required(ErrorMessage = "Password is required.")]
        public string Password
        {
            get { return _Password; }
            set { _Password = value; OnPropertyChanged(Password); }
        }

        private bool _IsRememberMe;
        public bool IsRememberMe
        {
            get { return _IsRememberMe; }
            set { _IsRememberMe = value; OnPropertyChanged("IsRememberMe"); }
        }


        private bool _isBusy;

        public bool IsBusy
        {
            get { return _isBusy; }
            set { _isBusy = value; OnPropertyChanged("IsBusy"); }
        }

        private string _busyContent;

        public string BusyContent
        {
            get { return _busyContent; }
            set { _busyContent = value; OnPropertyChanged("BusyContent"); }
        }

        private Branch _SelectedMaster;

        public Branch SelectedMaster
        {
            get { return _SelectedMaster; }
            set { _SelectedMaster = value; OnPropertyChanged("SelectedMaster");}
        }
        
        

        #endregion

        #region Command Properties
        public ICommand GridControlLoadCommand { get; set; }
        public ICommand LoginCommand { get; private set; }
        public ICommand LoginFormGotFocusCommand { get; private set; }
        public ICommand ResetCommand { get; private set; }
        public ICommand InputLoginFormTextChangeCommand { get; private set; }

        #endregion

        #region "INotifyDataErrorInfo members implementation"

        ObservableCollection<ValidationResult> validationResults;
        public ObservableCollection<ValidationResult> ValidationResults
        {
            get
            {
                return this.validationResults;
            }
            set
            {
                this.validationResults = value;
                this.OnPropertyChanged("ValidationResults");
            }
        }

        private readonly Dictionary<string, List<string>> errors;

        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        public IEnumerable GetErrors(string propertyName)
        {
            if ((!this.errors.ContainsKey(propertyName)) || string.IsNullOrEmpty(propertyName)) return this.errors;

            return this.errors[propertyName];
        }

        public bool HasErrors
        {
            get { return this.errors.Count > 0; }
        }

        public void Clear()
        {
            this.errors.Clear();
        }

        public void RemoveErrorFromProperty(string propertyName, string errorMessage = null, bool notifyErrorschanged = false)
        {
            if (!this.errors.ContainsKey(propertyName)) return;

            this.RemoveErrorFromPropertyIfErrorAlreadyExist(propertyName);

            if (notifyErrorschanged) this.NotifyErrorsChanged(propertyName);
        }

        private void RemoveErrorFromPropertyIfErrorAlreadyExist(string propertyName)
        {
            if (!this.errors.ContainsKey(propertyName)) return;

            this.errors[propertyName].Clear();
            if (this.errors[propertyName].Count == 0) this.errors.Remove(propertyName);
        }

        private void NotifyErrorsChanged(string propertyName)
        {
            if (this.ErrorsChanged != null)
                this.ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
        }

        public void AddErrorToProperty(string propertyName, string[] errorMessage, bool notifyErrorschanged = false)
        {
            this.RemoveErrorFromPropertyIfErrorAlreadyExist(propertyName);

            if (!this.errors.ContainsKey(propertyName)) this.errors.Add(propertyName, new List<string>());

            foreach (var message in errorMessage)
            {
                this.errors[propertyName].Add(message);
            }

            if (notifyErrorschanged) this.NotifyErrorsChanged(propertyName);
        }
        #endregion
    }


}
